#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "rtc.h"



struct RTC_TIME RTC_time;


static void (*RTC_Second_Callback)() = 0;
static void (*RTC_Minute_Callback)() = 0;

char MonthLength[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

ISR(TIMER0_OVF_vect)
{
    static char LeapMonth;

    RTC_time.SECOND++;               // increment second

	if (RTC_Second_Callback != 0)
	{
		RTC_Second_Callback();
	}

    if (RTC_time.SECOND == 60)
    {
        RTC_time.SECOND = 0;
        RTC_time.MINUTE++;

		if (RTC_Minute_Callback != 0)
		{
			RTC_Minute_Callback();
		}
        
        if (RTC_time.MINUTE > 59)
        {
            RTC_time.MINUTE = 0;
            RTC_time.HOUR++;
            
            if (RTC_time.HOUR > 23)
            {
                
                RTC_time.HOUR = 0;
                RTC_time.DAY++;

                // Check for leap year if month == February
                if (RTC_time.MONTH == 2)
                    if (!(RTC_time.YEAR & 0x0003))              // if (gYEAR%4 == 0)
                        if (RTC_time.YEAR%100 == 0)
                            if (RTC_time.YEAR%400 == 0)
                                LeapMonth = 1;
                            else
                                LeapMonth = 0;
                        else
                            LeapMonth = 1;
                    else
                        LeapMonth = 0;
                else
                    LeapMonth = 0;

                // Now, we can check for month length
                if (RTC_time.DAY > (MonthLength[RTC_time.MONTH] + LeapMonth))
                {
                    RTC_time.DAY = 1;
                    RTC_time.MONTH++;

                    if (RTC_time.MONTH > 12)
                    {
                        RTC_time.MONTH = 1;
                        RTC_time.YEAR++;
                    }
                }
            }
        }
    }
}


void RTC_init(void)
{
    //Delay(1000);            // wait for 1 sec to let the Xtal stabilize after a power-on,

    cli(); // mt __disable_interrupt();  // disabel global interrupt

	RTC_Minute_Callback = 0;
	RTC_Second_Callback = 0;

    cbiBF(TIMSK, TOIE0);             // disable OCIE2A and TOIE2

    ASSR = (1<<AS0);        // select asynchronous operation of Timer2

    TCNT0 = 0;              // clear TCNT2A
    TCCR0 |= (1<<CS02) | (1<<CS00);             // select precaler: 32.768 kHz / 128 = 1 sec between each overflow

    while((ASSR & 0x01) | (ASSR & 0x04));       // wait for TCN2UB and TCR2UB to be cleared

    TIFR = 0xFF;           // clear interrupt-flags
    sbiBF(TIMSK, TOIE0);     // enable Timer2 overflow interrupt

    sei(); // mt __enable_interrupt();                 // enable global interrupt

    // initial time and date setting
    RTC_time.SECOND  = 0;
    RTC_time.MINUTE  = 20;
    RTC_time.HOUR    = 02;
    // mt release timestamp
    RTC_time.DAY     = 28;
    RTC_time.MONTH   = 3;
    RTC_time.YEAR    = 2009;
}


void RTC_SetSecondCallback( void (*call)() )
{
	RTC_Second_Callback = call;
}

void RTC_SetMinuteCallback( void (*call)() )
{
	RTC_Minute_Callback = call;
}
